﻿using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens;
using ZL.IdentityServer4ClientConfig;

namespace PoemGame.SignalR
{
    public static class IDS4Extension
    {
        public static IServiceCollection AddIdentityServer4ApiNew(this IServiceCollection services, IConfiguration configurateion)
        {
            var cfg = configurateion.GetSection("IdentityServer4Api");
            var opt = new ApiOption();
            cfg.Bind(opt);

            services.AddCors(option => option.AddPolicy("cors",
                policy => policy.AllowAnyHeader()
                .AllowAnyMethod()
                .AllowCredentials()
                .WithOrigins(opt.CorsOrgins.ToArray())));

            // accepts any access token issued by identity server
            services.AddAuthentication("Bearer")
                .AddJwtBearer("Bearer", options =>
                {
                    options.Authority = opt.Authority;
                    options.RequireHttpsMetadata = opt.RequireHttpsMetadata;
                    options.TokenValidationParameters = new TokenValidationParameters
                    {
                        ValidateAudience = false
                    };
                    options.Events = new JwtBearerEvents
                    {
                        OnMessageReceived = context =>
                        {
                            var accessToken = context.Request.Query["access_token"];

                            // If the request is for our hub...
                            var path = context.HttpContext.Request.Path;
                            if (!string.IsNullOrEmpty(accessToken) &&
                                (path.StartsWithSegments("/gameHub") || path.StartsWithSegments("/gameCenterHub") || path.StartsWithSegments("/singlegamehub")))
                            {
                                // Read the token out of the query string
                                context.Token = accessToken;
                            }
                            return Task.CompletedTask;
                        }
                    };
                });

            // adds an authorization policy to make sure the token is for scope 'api1'
            services.AddAuthorization(options =>
            {
                foreach (var p in opt.Policies)
                {
                    options.AddPolicy(p.Name, policy =>
                    {
                        if (p.RequireAuthenticatedUser) policy.RequireAuthenticatedUser();
                        foreach (var c in p.Claims)
                        {
                            policy.RequireClaim(c.ClaimType, c.AllowValues.ToArray());
                        }

                    });
                }

            });
            return services;
        }
    }
}

